﻿using MongoDB.Driver;
using Sustainalytics.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.Auth.Service.GA
{
    public class GaUserRepository
    {
        private readonly IMongoCollection<User> _userCollection;
        private readonly IMongoCollection<ClientUser> _clientUserCollection;
        private readonly IMongoCollection<Account> _accountCollection;

        public GaUserRepository(
            IMongoCollection<User> userCollection,
            IMongoCollection<ClientUser> clientUserCollection,
            IMongoCollection<Account> accountCollection)
        {
            _userCollection = userCollection;
            _clientUserCollection = clientUserCollection;
            _accountCollection = accountCollection;
        }

        public virtual async Task<GaUser> GetByUserIdAsync(Guid userId)
        {
            var user = _userCollection.Find(x => x.Id == userId).SingleOrDefault();

            return await GetGaUser(user);
        }

        public virtual async Task<GaUser> GetByUsernameAsync(string username)
        {
            var parsedUserName = GetParsedUserName(username);
            var user = _userCollection.Find(x => x.Email.ToLowerInvariant() == parsedUserName).SingleOrDefault();

            return await GetGaUser(user);
        }

        private static string GetParsedUserName(string username) => (username ?? string.Empty).Trim().ToLowerInvariant();

        private async Task<GaUser> GetGaUser(User user)
        {
            if (user == null)
                return null;

            var clientUser = _clientUserCollection.Find(x => x.Id == user.Id).SingleOrDefaultAsync();
            var account = _accountCollection.Find(x => x.Id == user.AccountId).SingleOrDefaultAsync();

            return GetGaUser(user, await clientUser, await account);
        }

        private GaUser GetGaUser(User user, ClientUser clientUser, Account account)
        {
            if (clientUser == null || account == null)
                return null;

            return new GaUser
            {
                Id = user.Id,

                Status = (Status)user.Status,
                Email = user.Email,
                FirstName = user.FirstName,
                MiddleName = user.MiddleName,
                LastName = user.LastName,
                Username = user.Email,
                Password = clientUser.Password,
                PasswordExpirationDate = clientUser.PasswordExpirationDate,
                IsFakeIpUser = user.IsFakeIpUser,

                AccountId = user.AccountId,
                AccountName = user.Account,
                AccountTier = GetAccountTier(account),
                AccountManagerEmail = account?.AccountManager?.Email,
                AccountManagerName = account?.AccountManager?.FullName,
                ActiveEsgProfileId = GetActiveEsgProfileId(account),
                RelationshipType = (RelationshipType)account.RelationshipType,
                IsLegalAgreementAccepted = user.IsLegalAgreementAccepted,
                FirstTimeRRUserAccepted = user.FirstTimeUserAccepted?.IsRiskRatingAccepted ?? false,
                FirstTimeSPUserAccepted = user.FirstTimeUserAccepted?.IsSustainableProductsAccepted ?? false
            };
        }

        private int GetAccountTier(Account account)
        {
            if (account == null)
                return 3;

            if (account.PlatformTier == 0)
                return 1;

            return (int)account.PlatformTier - 100000000 + 1;
        }

        private Guid GetActiveEsgProfileId(Account account)
        {
            if (account == null)
                return Guid.Empty;

            return account.CurrentEsgProfile;
        }
    }
}
